package com.yys.gulimall.gulimallauthserver.controller;/*
 * @author zq
 */

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.netflix.ribbon.proxy.annotation.Http;
import com.yys.common.exception.BizCodeEnume;
import com.yys.common.to.user.MemberVo;
import com.yys.common.utils.R;
import com.yys.gulimall.gulimallauthserver.constant.AuthServerConstant;
import com.yys.gulimall.gulimallauthserver.feign.MemberFeignService;
import com.yys.gulimall.gulimallauthserver.feign.ThirdFeignService;
import com.yys.gulimall.gulimallauthserver.vo.UserLoginVo;
import com.yys.gulimall.gulimallauthserver.vo.UserRegistVo;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static com.yys.common.constant.AutherServerConstant.LOGIN_USER;

@Controller
@Log4j2
public class LoginController {

    @Autowired
    private ThirdFeignService thirdFeignService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private MemberFeignService memberFeignService;

    @GetMapping("/sms/sendCode")
    @ResponseBody
    public R sendCode(@RequestParam("phone") String phone) {
        //TODO 接口防刷
        String redisCode = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
        if(StringUtils.isNotBlank(redisCode)) {
            long codeTime = Long.parseLong(redisCode.split("_")[1]);
            if (System.currentTimeMillis() - codeTime < 60000) {
                // 60s 内不能再发
                return R.error(BizCodeEnume.SMS_CODE_EXCEPTION.getCode(),BizCodeEnume.SMS_CODE_EXCEPTION.getMsg());
            }
        }

        // 缓存验证码同时记录时间

        String code = UUID.randomUUID().toString().substring(0,5);
        String codeCache = code + "_" + System.currentTimeMillis();

        stringRedisTemplate.opsForValue().set(
                AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone, codeCache,10, TimeUnit.MINUTES);

        thirdFeignService.sendCode(phone,code);
        return R.ok();
    }

    @PostMapping("regist")
    public String regist(@Valid UserRegistVo registVo, BindingResult bindingResult, RedirectAttributes attributes) {
        if(bindingResult.hasErrors()) {
            HashMap<String, String> errors = new HashMap<>();

            bindingResult.getFieldErrors().forEach((item)->{
                String field = item.getField();
                String defaultMessage = item.getDefaultMessage();
                errors.put(field,defaultMessage);
            });

            //使用redirectAttribute进行重定向
            //addFlashAttribute只取一次
            attributes.addFlashAttribute("errors",errors);

            // 这里会报 post不支持
            // 这里路径映射默认转发是get请求,那我们可以直接去渲染页面即可
            // 需要重定向防止表单重复提交,写域名
            // 其实就是使用了session保存数据 TODO 分布式session问题
            return "redirect:http://auth.gulimall.com/reg.html";
        }
        // 远程服务来进行注册
        // 1. 校验验证码
        String code = registVo.getCode();

        String redisCode = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + registVo.getPhone());

        if(StringUtils.isNotBlank(redisCode)) {
            if(code.equals(redisCode.split("_")[0])) {
                // 验证码通过 删除redis缓存
                stringRedisTemplate.delete(AuthServerConstant.SMS_CODE_CACHE_PREFIX + registVo.getPhone());
                // 注册 调用member服务进行注册
                R regist = memberFeignService.regist(registVo);
                if(regist.getCode() == 0) {
                    //成功返回登录页
                    return "redirect:http://auth.gulimall.com/login.html";
                } else {
                    // 放入错误消息,重定向到注册页
                    HashMap<String, String> errors = new HashMap<>();
                    errors.put("msg", regist.getData("msg",new TypeReference<String>(){}));
                    attributes.addFlashAttribute("errors",errors);
                    return "redirect:http://auth.gulimall.com/reg.html";
                }
            } else {
                HashMap<String, String> errors = new HashMap<>();
                errors.put("code","验证码不匹配请重新发送");
                // 验证码为空,重定向到注册页
                attributes.addFlashAttribute("errors",errors);
                return "redirect:http://auth.gulimall.com/reg.html";
            }
        } else {
            HashMap<String, String> errors = new HashMap<>();
            errors.put("code","验证码不匹配请重新发送");
            // 验证码为空,重定向到注册页
            attributes.addFlashAttribute("errors",errors);
            return "redirect:http://auth.gulimall.com/reg.html";
        }
    }

    @PostMapping("/login")
    public String login(UserLoginVo userLoginVo, RedirectAttributes redirectAttributes, HttpSession session) {
        //TODO 分布式session
        // 远程登录
        R login = memberFeignService.login(userLoginVo);
        if (login.getCode() == 0) {
            // spring session
            MemberVo data = login.getData(new TypeReference<MemberVo>() {});
            session.setAttribute(LOGIN_USER,data);
            log.info("登录成功:{}",data);
            return "redirect:http://gulimall.com";
        } else {
            HashMap<String, String> errors = new HashMap<>();
            errors.put("msg",login.getData("msg",new TypeReference<String>(){}));
            redirectAttributes.addFlashAttribute("errors",errors);
            return "redirect:http://auth.gulimall.com/login.html";
        }
    }

    /**
     * 已经登录的用户不需要再次登录
     * */
    @GetMapping("/login.html")
    public String loginPage(HttpSession session) {
        Object loginUser = session.getAttribute(LOGIN_USER);
        if(ObjectUtils.isNull(loginUser)) {
            // 未登录
            return "login";
        } else {
            // 重定向到首页
            return "redirect:http://gulimall.com";
        }

    }
}
